# -*- coding: utf-8 -*-
 
from aip import AipSpeech  #百度语音识别库
import pyaudio             #麦克风声音采集库
import wave
import requests,json       #音乐搜索
import pygame              #mp3播放
import os
import time
import sys

""" 我的 APPID AK SK """
APP_ID = '15950952'
API_KEY = 'WhR3jyIAEDCzxQN8lFyawNND'
SECRET_KEY = 'VfcNUMRuGyNCq6CYj4CuiKCwIYKm1Fhe'
 
#定义采集声音文件参数
CHUNK = 1024
FORMAT = pyaudio.paInt16 #16位采集
CHANNELS = 1             #单声道
RATE = 16000             #采样率
RECORD_SECONDS = 9       #采样时长 定义为9秒的录音
WAVE_OUTPUT_FILENAME = "/home/pi/my_python_programe/myvoice.pcm"  #采集声音文件存储路径
 
def get_file_content(filePath):
	with open(filePath, 'rb') as fp:
		return fp.read()

# 读取paudio录制好的音频文件, 调用百度语音API, 设置api参数, 完成语音识别
#    client:AipSpeech对象
#    afile:音频文件
#    afmt:音频文件格式(wav)
def aip_get_asrresult(client, afile, afmt):
    # 选项参数:
    # cuid    String  用户唯一标识，用来区分用户，填写机器 MAC 地址或 IMEI 码，长度为60以内
    # dev_pid String  语言类型(见下表), 默认1537(普通话 输入法模型)
    # 识别结果已经被SDK由JSON字符串转为dict
	result = client.asr(get_file_content(afile), afmt, 16000, {"cuid": CUID, "dev_pid": DEV_PID,})
    #print(result)
    # 如果err_msg字段为"success."表示识别成功, 直接从result字段中提取识别结果, 否则表示识别失败
	if result["err_msg"] == "success.": 
        #print(result["result"])
		return result["result"]
	else:
        #print(result["err_msg"])
		return ""

#获取下载地址
def get_down_url(songid):
	req=requests.get("http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.song.play&format=jsonp&callback=jQuery17206073972467458864_1511011710426&songid=%s&_=1511011713541" %songid)
	print(req)
	req.encoding='utf-8'
	#print(json.loads(req.text))
	json1=json.loads(req.text.replace("jQuery17206073972467458864_1511011710426(","").replace(");",""))
	print("下载地址:",json1["bitrate"]['show_link'])
	return json1["bitrate"]['show_link']
#下载保存文件
def music_down(url,music_name,artistname):
	f=open("./mp3/"+music_name+'-'+artistname+'.mp3','wb')
	req_mp3=requests.get(url)
	f.write(req_mp3.content)
	f.close()
#调用百度AI，将文字转化为声音输出，用于提示音
def word_to_voice(text):
	i = 1
	result = client.synthesis(text, 'zh', 1, {
        'vol': 5, 'spd': 3, 'per': 3})
	if not isinstance(result, dict):
		with open('/home/pi/my_python_programe/audio.mp3', 'wb') as f:
			f.write(result)
			f.close()
	pygame.mixer.music.load('/home/pi/my_python_programe/audio.mp3')#text文字转化的语音文件
	pygame.mixer.music.play(loops=0)
	while pygame.mixer.music.get_busy() == True:
		if i == 1:
			i = 0
			print('waiting')
 
def word_to_voice1(text):
	i = 1
	result = client.synthesis(text, 'zh', 1, {
        'vol': 5, 'spd': 3, 'per': 3})
	if not isinstance(result, dict):
		with open('/home/pi/my_python_programe/audio1.mp3', 'wb') as f:
			f.write(result)
			f.close()
	pygame.mixer.music.load('/home/pi/my_python_programe/audio1.mp3')
	pygame.mixer.music.play(loops=0)
	while pygame.mixer.music.get_busy() == True:
		if i == 1:
			i = 0
			print('waiting')
 
#获得麦克风输入的声音文件，保存在myvoice.pcm
def  get_mic_voice_file(p):
	stream = p.open(format=FORMAT,
					channels=CHANNELS,
					rate=RATE,
					input=True,
					frames_per_buffer=CHUNK)
	print("* recording")
 
	frames = []
	for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
		data = stream.read(CHUNK)
		frames.append(data)
		# print(frames)
	print("* done recording")
	stream.stop_stream()
	stream.close()
	wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
	wf.setnchannels(CHANNELS)
	wf.setsampwidth(p.get_sample_size(FORMAT))
	wf.setframerate(RATE)
	wf.writeframes(b''.join(frames))
	wf.close()
	print('recording finished')
#获得麦克风输入的声音文件，保存在myvoice.pcm
def  get_mus_voice_file(p):
	stream = p.open(format=FORMAT,
					channels=CHANNELS,
					rate=RATE,
					input=True,
					frames_per_buffer=CHUNK)
	print("* recording")
 
	frames = []
	for i in range(0, int(RATE / CHUNK * 10)):
		data = stream.read(CHUNK)
		frames.append(data)
		# print(frames)
	print("* done recording")
	stream.stop_stream()
	stream.close()
	wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
	wf.setnchannels(CHANNELS)
	wf.setsampwidth(p.get_sample_size(FORMAT))
	wf.setframerate(RATE)
	wf.writeframes(b''.join(frames))
	wf.close()
	print('recording finished')
 
#百度语音识别出歌名文字并返回
def  baidu_get_song_name(client):
	results = client.asr(get_file_content(WAVE_OUTPUT_FILENAME), 'pcm', 16000, { 'dev_pid': 1536, })
	# print(results['result'])
	if results["err_msg"] == "success.": 
        #print(result["result"])
		song_name=results['result'][0]
		print(song_name)
		return song_name
	else:
        #print(result["err_msg"])
		return ""
 
#百度音乐下载歌曲，取自百度
def download_music_file(song_name):
	req_url = "http://sug.music.baidu.com/info/suggestion?format=json&word=%s&version=2&from=0&callback=window.baidu.sug&third_type=0&client_type=0&_=1511013032878" % song_name
	req_so = requests.get(req_url)
	a = -1
	data = json.loads(req_so.text.replace("window.baidu.sug(", "").replace(");", ""))
	print("歌单如下:")
	for i in data["data"]["song"]:
		print("\tsongid:" + str(i["songid"]), "音乐名字:" + i["songname"], "\t歌手:" + i["artistname"])
	word_to_voice1('请选择第几首歌')
	get_mic_voice_file(p) 
	mod = baidu_get_song_name(client)
	while mod =="":
		word_to_voice1('请选择第几首歌')
		get_mic_voice_file(p) 
		mod = baidu_get_song_name(client)
	while mod !="":	
		if mod == '第一首':
			a = 0
			break
		elif mod == '第二首':
			a = 1
			break
		elif mod == '第三首':
			a = 2
			break
		elif mod == '第四首':
			a = 3
			break
		elif mod == '第五首':
			a = 4
			break
		elif mod == '第六首':
			a = 5
			break
		elif mod == '第七首':
			a = 6
			break
		elif mod == '第八首':
			a = 7
			break
		elif mod == '第九首':
			a = 8
			break
		elif mod == '第十首':
			a = 9
			break
		elif mod == '第十一首':
			a = 10
			break
		elif mod == '第十二首':
			a = 11
			break
		else:
			a = -1
	print(mod, a)
	input_songid = data["data"]["song"][int(a)]["songid"]  #获取你要下载歌曲的songid
	for i in data["data"]["song"]:
		if input_songid == str(i["songid"]):
			url = get_down_url(i["songid"])
			music_down(url, i["songname"], i["artistname"])
			print("下载完成")
			music_name = i['songname']  # 获取MP3文件中的歌曲名
			artistname = i["artistname"]  # 获取MP3文件中的歌手名
	filename = '/home/pi/my_python_programe/mp3/' + music_name + '-' + artistname + '.mp3'
	print(filename)

	word_to_voice1('请欣赏歌曲'+str(music_name))
	return filename,music_name
	
def play_mp3(music_file):
	pygame.mixer.music.load(music_file)
	pygame.mixer.music.play(loops=0)  #该函数运行后立即返回，音乐一直在后台运行
 
def one_time_process(p):#一次麦克采样+语音识别+音乐下载+自动播放
	word_to_voice('请说出歌名')
	get_mic_voice_file(p)
	mod = baidu_get_song_name(client)
	while mod =="":
		word_to_voice('请说出歌名')
		get_mic_voice_file(p)
		mod = baidu_get_song_name(client)
	if mod == '退出网络模式':
		filename = '退出网络模式'
		music_name = ' '
	else:
		filename,music_name = download_music_file(mod)
	# play_mp3(filename)
	return filename,music_name

def change(p):
	word_to_voice('请选择模式')
	word_to_voice('本地模式或者网络模式')
	get_mic_voice_file(p) 
	mod = baidu_get_song_name(client)
	while mod =="":
		word_to_voice('请选择模式')
		word_to_voice('本地模式或者网络模式')
		get_mic_voice_file(p) 
		mod = baidu_get_song_name(client)
	# play_mp3(filename)
	return str(mod)

def gci(filepath,musics):
#遍历filepath下所有文件，包括子目录
	n = 0
	files = os.listdir(filepath)
	for fi in files:
		fi_d = os.path.join(filepath,fi)            
		if os.path.isdir(fi_d):
			gci(fi_d)                  
		else:
			n = n + 1
			musics.append(str(os.path.join(filepath,fi_d)))
			print(os.path.join(filepath,fi_d))	
	print(n)
	return n
 
if __name__=='__main__':
    #麦克风采集初始化、百度语音识别初始化、mp3文件播放初始化
	p = pyaudio.PyAudio()
	client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
	pygame.mixer.init()
	musics = []
	num = 0
	nums = 0
	while True:#循环调用麦克录音
		mod = change(p)
		if mod == '本地模式':
			nums = gci('/home/pi/my_python_programe/mp3/',musics)
			print(musics)
			play_mp3(musics[num])
			# while pygame.mixer.music.get_busy()==True:
			while True:
				get_mus_voice_file(p) 
				mods = baidu_get_song_name(client)
				# while mods =="":
					# get_mic_voice_file(p) 
					# mods = baidu_get_song_name(client)
				if pygame.mixer.music.get_busy()!=True:
					pygame.mixer.music.stop()
					num = num + 1
					if num > nums:
						num = nums
					play_mp3(musics[num])
				if mods == '下一首':
					print('下一首')
					pygame.mixer.music.stop()
					num = num + 1
					if num > nums:
						num = nums
					play_mp3(musics[num])
				if mods == '上一首':
					print('上一首')
					pygame.mixer.music.stop()
					num = num - 1
					if num < 0:
						num = 0
					play_mp3(musics[num])
				if mods == '暂停播放':
					print('暂停播放')
					pygame.mixer.music.pause()
				if mods == '继续播放':
					print('继续播放')
					pygame.mixer.music.unpause()
				if mods == '退出本地模式':
					m = 0
					break
		elif mod == '网络模式':
			t = 0
			while True:
				filename,musicname = one_time_process(p)
				if (filename,musicname) != (False,False) and (filename,musicname) != ('退出网络模式',' '):
					play_mp3(filename)
					m = 1
					# while pygame.mixer.music.get_busy()==True:
					print('歌曲：'+str(musicname)+'     正在播放！')
					print('时间：'+str(time.strftime("%X",time.localtime())))
					while True:
						get_mus_voice_file(p) 
						mods = baidu_get_song_name(client)
						while pygame.mixer.music.get_busy()==True:
							get_mic_voice_file(p) 
							mods = baidu_get_song_name(client)
							if mods == '暂停播放':
								print('暂停播放')
								pygame.mixer.music.pause()
							if mods == '继续播放':
								print('继续播放')
								pygame.mixer.music.unpause()
							if mods == '退出网络模式':
								m = 0
								break
						if m == 1:
							word_to_voice('歌曲播放结束  请重新选择')
							mods = ''
							t = 0
							print('歌曲播放结束！请重新选择！！')
							print('时间：'+str(time.strftime("%X",time.localtime())))
							break
						if mods == '退出网络模式':
							t = 1
							break
				if (filename,musicname) == ('退出网络模式',' '):
					break
				if t == 1:
					break
						
				